package com.black.utils.file;

import lombok.Getter;

import java.io.File;
import java.util.Arrays;
import java.util.List;

/**
 * @author ylx
 */
@Getter
public enum FileTypeEnum
{
    PDF("pdf", ""),

    PPT("ppt", ""),

    PPTX("pptx", ""),

    DOC("doc", ""),

    DOCX("docx", ""),

    XLS("xls", ""),

    XLSX("xlsx", "本质为.zip压缩文件," +
        "其中包含xl目录,包含工作标的数据和样式, 即worksheets目录的sheet1.xml等和styles.xml" +
        "docProps目录,包含文档的属性信息,_rels包含与该文件相关的关系信息" +
        "Content_Types.xml定义了文档中包含的各种内容类型"),

    CSV("csv", ""),

    PROPERTIES("properties", ""),

    XML("xml", ""),

    YML("yml", ""),

    YAML("yaml", ""),

    HTML("html", ""),

    TXT("txt", ""),

    JSON("json", ""),

    SQL("sql", ""),

    JPEG("jpeg", "data:image/jpeg;base64,"),

    JPG("jpg", "data:image/jpeg;base64,"),

    PNG("png", "data:image/png;base64,"),

    SVG("png", "data:image/svg;base64,"),

    GIF("gif", ""),

    ICO("ico", ""),

    MP4("mp4", ""),

    MP3("mp3", ""),

    WAV("wav", ""),

    ZIP("zip", ""),

    RAR("rar", ""),

    TAR("tar", ""),

    GZ("gz", ""),

    TGZ("tgz", ""),

    JAR("jar", ""),

    CLASS("class", ""),

    FIT("fit", "佳明,行者等大多运动记录文件格式"),

    GPX("gpx", "顽鹿运动记录文件格式"),

    DIR(File.separator, "目录"),

    UNKNOWN("", ""),
    ;

    private final String suffix;

    private final String extension;

    private final String description;

    public static final String FILE_SEPARATOR = ".";

    public static final String PATH_SEPARATOR = File.separator;

    FileTypeEnum(String extension, String description)
    {
        this.suffix = extension.isEmpty() ? extension : FILE_SEPARATOR + extension;
        this.extension = extension;
        this.description = description;
    }

    /**
     * 判断文件名是否为该类型
     *
     * @param filename 文件名或路径名
     * @return true/false
     */
    public boolean is(String filename)
    {
        if (this == UNKNOWN)
        {
            throw new IllegalArgumentException("The type of the file cannot be determined");
        }
        if (this == DIR)
        {
            throw new IllegalArgumentException("The type not supported this method, please use another");
        }
        String suffix = getSuffix(filename);
        return this.suffix.equals(suffix);
    }

    /**
     * 判断文件是否为该类型
     *
     * @param file 文件
     * @return true/false
     */
    public boolean is(File file)
    {
        if (this == DIR)
        {
            return file.isDirectory();
        }
        return is(file.getName());
    }

    public static List<FileTypeEnum> getImageTypes()
    {
        return Arrays.asList(PNG, JPG, JPEG, GIF, ICO, SVG);
    }

    public static List<FileTypeEnum> getVideoTypes()
    {
        return Arrays.asList(MP4, MP3, WAV);
    }

    public static List<FileTypeEnum> getTextTypes()
    {
        return Arrays.asList(TXT, JSON, SQL);
    }

    public static List<FileTypeEnum> getCompressTypes()
    {
        return Arrays.asList(ZIP, RAR, TAR, GZ, TGZ);
    }

    public static List<FileTypeEnum> getPropertyTypes()
    {
        return Arrays.asList(PROPERTIES, XML, YML, YAML);
    }

    public static List<FileTypeEnum> getOfficeTypes()
    {
        return Arrays.asList(PDF, PPT, PPTX, DOC, DOCX, XLS, XLSX, CSV);
    }

    /**
     * 根据文件名获取文件类型
     *
     * @param filename 文件名或路径名
     * @return 文件类型
     */
    public static FileTypeEnum getType(String filename)
    {
        String suffix = getSuffix(filename);
        return Arrays.stream(values()).filter(type -> type.suffix.equals(suffix)).findFirst().orElse(UNKNOWN);
    }

    /**
     * 根据文件获取文件类型
     *
     * @param file 文件
     * @return 文件类型
     */
    public static FileTypeEnum getType(File file)
    {
        return getType(file.getName());
    }

    /**
     * 获取文件后缀名
     * 传入文件名返回对应的后缀.xxx
     *
     * @param filename 类型或文件名
     * @return 后缀名
     */
    public static String getSuffix(String filename)
    {
        if (filename.contains(FILE_SEPARATOR))
        {
            return filename.substring(filename.lastIndexOf(FILE_SEPARATOR)).toLowerCase();
        }
        return null;
    }

    /**
     * 获取文件后缀名
     * 传入文件名返回对应的后缀.xxx
     *
     * @param file 文件名
     * @return 后缀名
     */
    public static String getSuffix(File file)
    {
        return getSuffix(file.getName());
    }

    /**
     * 获取文件前缀
     *
     * @param filename 文件名/路径名
     * @return 文件名或全路径名
     */
    public static String getPrefix(String filename)
    {
        return filename.substring(0, filename.lastIndexOf(FILE_SEPARATOR));
    }

    /**
     * 获取文件前缀
     *
     * @param file 文件
     * @return 文件名
     */
    public static String getPrefix(File file)
    {
        return getPrefix(file.getName());
    }

    /**
     * 获取文件绝对路径前缀
     *
     * @param file 文件
     * @return 绝对路径加文件名
     */
    public static String getAbsolutePrefix(File file)
    {
        return getPrefix(file.getAbsolutePath());
    }

    /**
     * 获取文件名拓展名
     *
     * @param filename 文件名或路径名
     * @return 拓展名
     */
    public static String getExtension(String filename)
    {
        if (filename.contains(FILE_SEPARATOR))
        {
            return filename.substring(filename.lastIndexOf(FILE_SEPARATOR) + 1);
        }
        return "";
    }

    /**
     * 获取文件名拓展名
     *
     * @param file 文件
     * @return 拓展名
     */
    public static String getExtension(File file)
    {
        return getExtension(file.getName());
    }

    /**
     * 转换文件拓展名
     *
     * @param filename 文件名/路径名
     * @param type     文件类型
     * @return 转换后的文件名/路径名
     */
    public static String transferExtension(String filename, FileTypeEnum type)
    {
        FileTypeEnum sourceType = getType(filename);
        if (sourceType == DIR)
        {
            // 只有结尾为/ 才能获取到DIR类型
            return filename.substring(0, filename.lastIndexOf(FILE_SEPARATOR) - 1) + type.suffix;
        }
        if (sourceType == UNKNOWN)
        {
            return filename + type.suffix;
        }
        if (sourceType == type)
        {
            return filename;
        }
        return filename.replace(sourceType.suffix, type.suffix);
    }

    public static boolean isImage(String filename)
    {
        String extension = getExtension(filename);
        return getImageTypes().stream().anyMatch(type -> type.getExtension().equals(extension));
    }

    public static boolean isImage(File file)
    {
        return isImage(file.getName());
    }

    public static boolean isOffice(String filename)
    {
        String extension = getExtension(filename);
        return getOfficeTypes().stream().anyMatch(type -> type.getExtension().equals(extension));
    }

    public static boolean isOffice(File file)
    {
        return isOffice(file.getName());
    }

    public static boolean isProperty(String filename)
    {
        String extension = getExtension(filename);
        return getPropertyTypes().stream().anyMatch(type -> type.getExtension().equals(extension));
    }

    public static boolean isProperty(File file)
    {
        return isProperty(file.getName());
    }

    public static boolean isText(String filename)
    {
        String extension = getExtension(filename);
        return getTextTypes().stream().anyMatch(type -> type.getExtension().equals(extension));
    }

    public static boolean isText(File file)
    {
        return isText(file.getName());
    }

    public static boolean isVideo(String filename)
    {
        String extension = getExtension(filename);
        return getVideoTypes().stream().anyMatch(type -> type.getExtension().equals(extension));
    }

    public static boolean isVideo(File file)
    {
        return isVideo(file.getName());
    }

    public static boolean isCompress(String filename)
    {
        String extension = getExtension(filename);
        return getCompressTypes().stream().anyMatch(type -> type.getExtension().equals(extension));
    }

    public static boolean isCompress(File file)
    {
        return isCompress(file.getName());
    }

}
